use std::thread;

#[derive(Debug, PartialEq, Copy, Clone)]
enum ShirtColor {
    Red,
    Blue,
}

struct Inventory {
    shirts: Vec<ShirtColor>,
}

impl Inventory {
    fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
        user_preference.unwrap_or_else(|| self.most_stocked())
    }

    fn most_stocked(&self) -> ShirtColor {
        let mut num_red = 0;
        let mut num_blue = 0;

        for color in &self.shirts {
            match color {
                ShirtColor::Red => num_red += 1,
                ShirtColor::Blue => num_blue += 1,
            }
        }
        if num_red > num_blue {
            ShirtColor::Red
        } else {
            ShirtColor::Blue
        }
    }
}

pub fn closure_exercise() {
    let store = Inventory {
        shirts: vec![ShirtColor::Blue, ShirtColor::Red, ShirtColor::Blue],
    };

    let user_pref1 = Some(ShirtColor::Red);
    let giveaway1 = store.giveaway(user_pref1);
    println!(
        "The user with preference {:?} gets {:?}",
        user_pref1, giveaway1
    );

    let user_pref2 = None;
    let giveaway2 = store.giveaway(user_pref2);
    println!(
        "The user with preference {:?} gets {:?}",
        user_pref2, giveaway2
    );

    let add_1 = |x: i32| -> i32 { x + 1 };
    let add_2 = |x| { x + 1 };
    let add_3 = |x| x + 1;
    println!("{}", add_1(1));
    println!("{}", add_2(1));
    println!("{}", add_3(1));

    let example_closure = |x| x;
    println!("{}", example_closure("123"));
    // 类型已经确定，再更改则编译错误
    // println!("{}", example_closure(1));

    let mut s1 = String::from("test");
    let x1 = || println!("{s1}");
    // let mut x1 = || s1.push_str("1");
    // let x1 = move || println!("{s1}");
    // println!("before borrown {s1}");
    x1();
    println!("after borrown {s1}");

    let list = vec![1, 2, 3];
    println!("Before defining closure: {:?}", list);

    thread::spawn(move || println!("From thread: {:?}", list))
        .join()
        .unwrap();

    thread::spawn(|| println!("1"));
}

trait Component {
    fn draw(&self);
}

struct Button {

}

impl Component for Button {
    fn draw(&self) {
        println!("draw a button");
    }
}

struct Text {

}

impl Component for Text {
    fn draw(&self) {
        println!("draw a text");
    }
}

struct ComponentList {
    list: Vec<Box<dyn Component>>
}

impl ComponentList {
    fn draw_ui(&self) {
        for component in &self.list {
            component.draw();
        }
    }
}

 pub fn draw_ui() {
    let button = Button{};
    let text = Text{};
    let component_list = ComponentList{
        list: vec![Box::new(button), Box::new(text)]
    };

    component_list.draw_ui(); 
}
